#include "core.h"
#include "IShellContextMenu.h"
#include <Shlwapi.h>
#include <Winnetwk.h>
#include <propkey.h>

#define CMD_FIRST 1
#define CMD_LAST 30000
#define CMD_ADVANCED_SHARE 109

HHOOK CurrentHook;
IShellContextMenu *CurrentHookedContextMenu;

WPARAM PP;

// ....................................................................................................................
// Exportovana funkcia: Zobrazenie shell context menu
// Vstup:
//			pHandle - handle okna pre vlastnictvo menu
//			pObject - zoznam nazvov objektov oddelenych znakom 0x1
//			pX - X pozicia zobrazenia menu
//			pY - Y pozicia zobrazenia menu
// Vystup:
//			Ziaden
// ....................................................................................................................
void __stdcall ShowShellContextMenu(HWND pHandle, PCHAR pObjects, INT32 pX, INT32 pY) {
	IString *S = new IString(pObjects); // Prevediem na retazec
	IStringList *L = new IStringList(); L->CreateFromString(S, 0x1, false); // Extrahujem zoznam

	IShellContextMenu *M = new IShellContextMenu(); // Vytvorim objekt
	M->ShowContextMenu(pHandle, L, pX, pY); // Zobrazim menu

	delete M; // Zrusim objekty
	delete L;
	delete S;
}
// ....................................................................................................................

// ....................................................................................................................
// Vstup:
//			pHandle - handle okna pre vlastnictvo zobrazenie dialogu funkcie
//			pObject - zoznam nazvov objektov oddelenych znakom 0x1
//			pCommand - prikaz na vykonanie
// Vystup:
//			Ziaden
// ....................................................................................................................
void __stdcall ExecuteShellCommand(HWND pHandle, PCHAR pObjects, PCHAR pCommand) {
	IString *S = new IString(pObjects); // Prevediem na retazec
	IStringList *L = new IStringList(); L->CreateFromString(S, 0x1, false); // Extrahujem zoznam

	IShellContextMenu *M = new IShellContextMenu(); // Vytvorim objekt
	M->ExecuteShellCommand(pHandle, L, pCommand); // Volam vykonanie

	delete M; // Zrusim objekty
	delete L;
	delete S;
}
// ....................................................................................................................

// ....................................................................................................................
// Vstup:
//			pHandle - handle okna pre vlastnictvo zobrazenie dialogu funkcie
//			pObject - zoznam nazvov objektov oddelenych znakom 0x1
// Vystup:
//			Ziaden
// ....................................................................................................................
void __stdcall ShowItemPropertyWindow(HWND pHandle, PCHAR pObject) {
	IString *S = new IString(pObject); // Prevediem na retazec
	IStringList *L = new IStringList(); L->CreateFromString(S, 0x1, false); // Extrahujem zoznam

	IShellContextMenu *M = new IShellContextMenu(); // Vytvorim objekt
	M->ExecuteShellCommand(pHandle, L, "properties"); // Volam vykonanie

	delete M; // Zrusim objekty
	delete L;
	delete S;
}
// ....................................................................................................................

// ....................................................................................................................
// Vstup:
//			pHandle - handle okna pre vlastnictvo zobrazenie dialogu funkcie
//			pObject - nazov priecinku na zdielanie
// Vystup:
//			Ziaden
// ....................................................................................................................
void __stdcall ShowAdvancedShareWindow(HWND pHandle, PCHAR pObject) {
	IStringList *L = new IStringList(); L->Add(pObject); // Extrahujem zoznam

	IShellContextMenu *M = new IShellContextMenu(); // Vytvorim objekt
	M->ExecuteShellCommand(pHandle, L, "Windows.ShareSpecificUsers"); // Volam vykonanie

	delete M; // Zrusim objekty
	delete L;
}
// ....................................................................................................................

// ....................................................................................................................
// Hook precedura
// ....................................................................................................................
LRESULT CALLBACK CallWndProc_IShellMenu(INT32 nCode, WPARAM wParam, LPARAM lParam) {
	if (nCode >= 0) {
		if (CurrentHookedContextMenu != NULL) CurrentHookedContextMenu->CallHookProcedure((CWPSTRUCT*)lParam);
		return 0;
	}
	return ::CallNextHookEx(CurrentHook, nCode, wParam, lParam); // Volam nasledujuce hook
}
// ....................................................................................................................

// ....................................................................................................................
// Konstruktor
// Vstup:
//			Ziaden
// Vystup:
//			Ziaden
// ....................................................................................................................
IShellContextMenu::IShellContextMenu(void) {
	FContextMenu = NULL;
	FContextMenu2 = NULL;
	FContextMenu3 = NULL;
	FDesktopFolder = NULL;
	FParentFolder = NULL;
	FPidls = NULL; FPidlCount = 0;
}
// ....................................................................................................................
// ....................................................................................................................
// Destruktor
// Vstup:
//			Ziaden
// Vystup:
//			Ziaden
// ....................................................................................................................
IShellContextMenu::~IShellContextMenu(void) {
	ReleaseAll(); // Uvolnim
}
// ....................................................................................................................
// ....................................................................................................................
// Ziskanie desktop priecinku
// Vstup:
//			Ziaden
// Vystup:
//			odkaz na desktop folder
// ....................................................................................................................
IShellFolder* __fastcall IShellContextMenu::GetDesktopFolder(void) {
	if (FDesktopFolder == NULL) {
		if (SHGetDesktopFolder(&FDesktopFolder) != S_OK) return NULL;
	}
	return FDesktopFolder;
}
// ....................................................................................................................
// ....................................................................................................................
// Uvolnenie vsetkych objektov
// Vstup:
//			Ziaden
// Vystup:
//			Ziaden
// ....................................................................................................................
void __fastcall IShellContextMenu::ReleaseAll(void) {

	if (FContextMenu != NULL) FContextMenu->Release(); // Uvolnenie
	if (FContextMenu2 != NULL) FContextMenu2->Release();
	if (FContextMenu3 != NULL) FContextMenu3->Release();
	if (FDesktopFolder != NULL) FDesktopFolder->Release();
	if (FParentFolder != NULL) FParentFolder->Release();
	if (FPidls != NULL) FreePidls(FPidls, FPidlCount);

	FContextMenu = NULL; // Inicializacia
	FContextMenu2 = NULL;
	FContextMenu3 = NULL;
	FDesktopFolder = NULL;
	FParentFolder = NULL;
	FPidls = NULL; FPidlCount = 0;
}
// ....................................................................................................................
// ....................................................................................................................
// Ziskanie rodicovkeho priecinku
// Vstup:
//			pValue - plny nazov
// Vystup:
//			odkaz
// ....................................................................................................................
IShellFolder* __fastcall IShellContextMenu::GetParentFolder(CONST_PCHAR pValue) {
	if (FParentFolder == NULL) {
		IShellFolder *DF = GetDesktopFolder();
		if (DF == NULL) return NULL; // Chyba?

		IString S(pValue); PWCHAR S1 = S.PWChar();

		LPITEMIDLIST pidl;
		ULONG cbEaten;
		DWORD dwAttribs = 0;
		CHAR BUF[MAX_PATH + 2];

		if (DF->ParseDisplayName(NULL, NULL, S1, &cbEaten, &pidl, &dwAttribs) != S_OK) {
			delete S1;
			return NULL;
		}

		STRRET* Strret = (STRRET*)CoTaskMemAlloc(MAX_PATH * 2 + 4);
		memset(Strret, 0, sizeof(STRRET));
		DF->GetDisplayNameOf(pidl, SHGDN_FORPARSING, Strret);
		StrRetToBuf(Strret, pidl, BUF, MAX_PATH); // Ziskam CHAR hodnotu
		CoTaskMemFree(Strret); // Uvolnim pamat
		delete S1; // Uvolnim wchar hodnotu

		FParentFolderString = pValue[0] == 0 ? "" : BUF; // Ulozim

		LPSHELLFOLDER V;
		if (DF->BindToObject(pidl, NULL, IID_IShellFolder, (PVOID*)&V) != S_OK) {
			CoTaskMemFree(pidl); // Uvolnim pamat
			return NULL;
		}

		CoTaskMemFree(pidl); // Uvolnim pamat
		FParentFolder = (IShellFolder*)V; // Ulozim 
	}
	return FParentFolder; // Vratim vysledok
}
// ....................................................................................................................
// ....................................................................................................................
// Zobrazenie context menu
// Vstup:
//			pParent - rodicovske okno
//			pNames - zoznam nazvov objektov
//			pX, pY - pozicia menu
// Vystup:
//			Ziaden
// ....................................................................................................................
void __fastcall IShellContextMenu::ShowContextMenu(HWND pParent, IStringList *pNames, INT32 pX, INT32 pY) {
	ReleaseAll(); // Uvolnim vsetko
	if (pNames->Count() == 0) return; // Nie je co zobrazit?
	if (CreatePidls(pNames) == NULL) return; 
	if (!GetContextMenuInterfaces(FParentFolder, FPidls, FPidlCount)) return;

	HMENU M = ::CreatePopupMenu();

	FContextMenu->QueryContextMenu(M, 0, CMD_FIRST, CMD_LAST, CMF_EXPLORE);

	CurrentHookedContextMenu = this;
	CurrentHook = ::SetWindowsHookEx(WH_CALLWNDPROC, CallWndProc_IShellMenu, NULL, ::GetCurrentThreadId());

	::GetCursorPos(&FContentMenuStartPoint);
	INT32 CmdID = ::TrackPopupMenu(M, TPM_LEFTALIGN | TPM_TOPALIGN | TPM_LEFTBUTTON | TPM_RETURNCMD, pX == -1 ? FContentMenuStartPoint.x : pX, pY == -1 ? FContentMenuStartPoint.y : pY, 0, pParent, NULL); // Zobrazim menu
	if (CmdID == 0) CmdID = -1; 

	::UnhookWindowsHookEx(CurrentHook);
	CurrentHookedContextMenu = NULL;

//	CHAR BUF[200]; // Ziskanie verb prikazu
//	INT32 R = FContextMenu->GetCommandString(CmdID - 1, GCS_VERBA, NULL, BUF, 199);

	if (CmdID != -1) { // Je vybrata volba?
		IString S; 
		S = FParentFolderString;
		if (S == "") { // Prazdny rodic?
			if (pNames->Count() == 1) { // Je len jedna polozka?
				S = pNames->GetString(0);
			}
		}
		InvokeCommand(pParent, FContextMenu, CmdID, S.PChar());
	}

	::DestroyMenu(M);
}
// ....................................................................................................................
// ....................................................................................................................
// Uvolnenie zoznam pidl
// Vstup:
//			pList - zoznam na uvolnenie
// Vystup:
//			Ziaden
// ....................................................................................................................
void __fastcall IShellContextMenu::FreePidls(LPITEMIDLIST *pList, INT32 pCount) {
	for (INT32 i = 0; i < pCount; i++) {
		if (pList[i] != NULL) CoTaskMemFree(pList[i]); // Uvolnim pamat
	}
	delete pList; // Zrusim zoznam
}
// ....................................................................................................................
// ....................................................................................................................
// Vytvorenie zoznamu pidl
// Vstup:
//			pNames - zoznam nazvov
// Vystup:
//			zoznam pidl
// ....................................................................................................................
LPITEMIDLIST* __fastcall IShellContextMenu::CreatePidls(IStringList *pNames) {
	if (FPidls == NULL) {
		IString S;
		IShellFolder *Parent;

		ICore::ExtractPath(pNames->GetString(0), &S);
		if (S == "") { // Ziadny rodic?
			Parent = GetParentFolder("");
			if (Parent == NULL) return NULL; // Chyba?
		}
		else {
			Parent = GetParentFolder(S.PChar());
			if (Parent == NULL) Parent = GetDesktopFolder();
			if (Parent == NULL) return NULL;
		}

		INT32 C = pNames->Count();
		FPidls = new LPITEMIDLIST[C]; // Alokujem
		for (INT32 i = 0; i < C; i++) FPidls[i] = NULL; // Inicializujem

		PWCHAR S1;
		IString S2;

		for (INT32 i = 0; i < C; i++) { // Prejdem vsetky nazvy
			LPITEMIDLIST pidl = NULL;
			ULONG cbEaten;
			DWORD dwAttribs = 0;
			ICore::ExtractName(pNames->GetString(i), &S2);
			S1 = S2.PWChar();
			if (Parent->ParseDisplayName(NULL, NULL, S1, &cbEaten, &pidl, &dwAttribs) != S_OK) { // Ziskam pidl
				delete S1;
				FreePidls(FPidls, C);
				FPidls = NULL;
				return NULL;
			}
			delete S1; // Zrusim wchar retazec
			FPidls[i] = pidl;
		}

		FPidlCount = C; // Ulozim pocet
	}
	return FPidls;
}
// ....................................................................................................................
// ....................................................................................................................
// Ziskanie interface na shell menu
// Vstup:
//			pParentFolder - rodicovsky folder
//			pList - zoznam objektov
//			pCount - pocet objektov
// Vystup:
//			true / false
// ....................................................................................................................
bool __fastcall IShellContextMenu::GetContextMenuInterfaces(IShellFolder *pParentFolder, LPITEMIDLIST *pList, INT32 pCount) {
	if (pParentFolder->GetUIObjectOf(NULL, pCount, (LPCITEMIDLIST*)pList, IID_IContextMenu, NULL, (PVOID*)&FContextMenu) != S_OK) return false; // Volam ziskanie objektu
	if (FContextMenu->QueryInterface(IID_IContextMenu2, (PVOID*)&FContextMenu2) != S_OK) {
		FContextMenu2 = NULL;
	}
	if (FContextMenu->QueryInterface(IID_IContextMenu3, (PVOID*)&FContextMenu3) != S_OK) {
		FContextMenu3 = NULL;
	}

	return true;
}
// ....................................................................................................................
// ....................................................................................................................
// Volana funkcia z hook procedury
// Vstup:
//			pParam - parameter
// Vystup:
//			Ziaden
// ....................................................................................................................
void __fastcall IShellContextMenu::CallHookProcedure(CWPSTRUCT *pParam) {
	INT32 R;
	if ((pParam->message == WM_MENUCHAR) && (FContextMenu3 != NULL)) {
		R = ((IContextMenu3*)FContextMenu3)->HandleMenuMsg2(pParam->message, pParam->wParam, pParam->lParam, NULL);
		return;
	}
	if ((pParam->message == WM_INITMENUPOPUP) && (FContextMenu2 != NULL)) {
		R = ((IContextMenu2*)FContextMenu2)->HandleMenuMsg(pParam->message, pParam->wParam, pParam->lParam);
		return;
	}
	if ((pParam->message == WM_MEASUREITEM) && (FContextMenu2 != NULL)) {
		R = ((IContextMenu2*)FContextMenu2)->HandleMenuMsg(pParam->message, pParam->wParam, pParam->lParam);
		return;
	}
	if ((pParam->message == WM_DRAWITEM) && (FContextMenu2 != NULL)) {
		R = ((IContextMenu2*)FContextMenu2)->HandleMenuMsg(pParam->message, pParam->wParam, pParam->lParam);
		return;
	}
}
// ....................................................................................................................
// ....................................................................................................................
// Spustenie prikazu
// Vstup:
//			pHandle - handle rodicovskeho okna
//			pMenu - smernik na menu
//			pCmdID - ID prikazu
//			pFolderName - nazov priecinku
//			pX, pY - pozicia
// Vystup:
//			Ziaden
// ....................................................................................................................
void __fastcall IShellContextMenu::InvokeCommand(HWND pHandle, IContextMenu *pMenu, UINT32 pCmdID, CONST_PCHAR pFolderName, bool pCtrl, bool pShift, INT32 pX, INT32 pY) {
	CMINVOKECOMMANDINFOEX Invoke;
	memset(&Invoke, 0, sizeof(CMINVOKECOMMANDINFOEX));
	Invoke.cbSize = sizeof(CMINVOKECOMMANDINFOEX);
	Invoke.hwnd = pHandle;
    Invoke.lpVerb = MAKEINTRESOURCE(pCmdID - 1);
    Invoke.lpDirectory = pFolderName;
	Invoke.ptInvoke = FContentMenuStartPoint;

	Invoke.fMask = CMIC_MASK_ASYNCOK | CMIC_MASK_PTINVOKE;
    Invoke.nShow = SW_SHOWNORMAL;
	HRESULT R = pMenu->InvokeCommand((CMINVOKECOMMANDINFO*)&Invoke); // Vykonanie prikazu

	//delete S1;
}
// ....................................................................................................................
// ....................................................................................................................
// Vykonanie prikazu dostupneho zo shell menu
// Vstup:
//			pParent - rodicovske okno
//			pNames - zoznam nazvov objektov
//			pOperation - kod operacie
// Vystup:
//			Ziaden
// ....................................................................................................................
void __fastcall IShellContextMenu::ExecuteShellCommand(HWND pParent, IStringList *pNames, CONST_PCHAR pOperation) {
	ReleaseAll(); // Uvolnim vsetko
	if (pNames->Count() == 0) return; // Nie je co zobrazit?
	if (CreatePidls(pNames) == NULL) return; 
	if (!GetContextMenuInterfaces(FParentFolder, FPidls, FPidlCount)) return;

	HMENU M = ::CreatePopupMenu();

	CurrentHookedContextMenu = this;
	CurrentHook = ::SetWindowsHookEx(WH_CALLWNDPROC, CallWndProc_IShellMenu, NULL, ::GetCurrentThreadId());

	FContextMenu->QueryContextMenu(M, 0, CMD_FIRST, CMD_LAST, CMF_EXPLORE | CMF_NORMAL);

	INT32 CmdID = FindFunctionCommandID(M, (PCHAR)pOperation); // Hladam ID pre danu operaciu

	::UnhookWindowsHookEx(CurrentHook);
	CurrentHookedContextMenu = NULL;

	::GetCursorPos(&FContentMenuStartPoint); // Pozicia okna

	if (CmdID != -1) { // Najdeny prikaz?
		IString S; 
		S = FParentFolderString;
		InvokeCommand(pParent, FContextMenu, CmdID, S.PChar());
	}

	::DestroyMenu(M);
}
// ....................................................................................................................
// ....................................................................................................................
// Vyhladanie ID funkcie podla jej verb kodu
// Vstup:
//			M - menu
//			pVerb - verb kod
// Vystup:
//			-1 nenasiel alebo ID funkcie
// ....................................................................................................................
INT32 __fastcall IShellContextMenu::FindFunctionCommandID(HMENU M, PCHAR pVerb) {
	CHAR BUF[256];
	int C = ::GetMenuItemCount(M); // Pocet poloziek

	for (int i = 0; i < C; i++) {

		INT32 pID = ::GetMenuItemID(M, i); // Ziskam ID
		INT32 R;
		if (pID >= CMD_FIRST) { // Je platne?
			R = FContextMenu->GetCommandString(pID - CMD_FIRST, GCS_VERBA, NULL, BUF, 250); // Ziskam verb
			if ((R == S_OK) && (stricmp(BUF, pVerb) == 0)) return pID; // R=vna sa?
		}

		HMENU M1 = ::GetSubMenu(M, i); // Ziskam podmenu
		if (M1 == NULL) continue; // Nie je...

		((IContextMenu2*)FContextMenu2)->HandleMenuMsg(WM_INITMENUPOPUP, (WPARAM)M1, i); // Vytvorim podmenu

		R = FindFunctionCommandID(M1, pVerb); // Hladam funkciu v podmenu
		if (R != -1) return R; // Nasiel som?
	}
	return -1; // Nic som nenasiel
}
// ....................................................................................................................
// ....................................................................................................................
// Vykonanie prikazu dostupneho zo shell menu
// Vstup:
//			pParent - rodicovske okno
//			pNames - zoznam nazvov objektov
//			pOperation - kod operacie
// Vystup:
//			Ziaden
// ....................................................................................................................
void __fastcall IShellContextMenu::ExecuteShellCommand(HWND pParent, IStringList *pNames, INT32 pOperation) {
	ReleaseAll(); // Uvolnim vsetko
	if (pNames->Count() == 0) return; // Nie je co zobrazit?
	if (CreatePidls(pNames) == NULL) return; 
	if (!GetContextMenuInterfaces(FParentFolder, FPidls, FPidlCount)) return;

	HMENU M = ::CreatePopupMenu();

	CurrentHookedContextMenu = this;
	CurrentHook = ::SetWindowsHookEx(WH_CALLWNDPROC, CallWndProc_IShellMenu, NULL, ::GetCurrentThreadId());

	FContextMenu->QueryContextMenu(M, 0, CMD_FIRST, CMD_LAST, CMF_EXPLORE | CMF_NORMAL);

	::UnhookWindowsHookEx(CurrentHook);
	CurrentHookedContextMenu = NULL;

	::GetCursorPos(&FContentMenuStartPoint);

	IString S; 
	S = FParentFolderString;
	InvokeCommand(pParent, FContextMenu, pOperation, S.PChar());

	::DestroyMenu(M);
}
// ....................................................................................................................

// ....................................................................................................................
// Spustenie prikazu
// Vstup:
//			pHandle - handle rodicovskeho okna
//			pMenu - smernik na menu
//			pCmdID - ID prikazu
//			pFolderName - nazov priecinku
//			pX, pY - pozicia
// Vystup:
//			Ziaden
// ....................................................................................................................
void __fastcall IShellContextMenu::InvokeCommand(HWND pHandle, IContextMenu *pMenu, CONST_PCHAR pCmdID, CONST_PCHAR pFolderName, bool pCtrl, bool pShift, INT32 pX, INT32 pY) {
	CMINVOKECOMMANDINFOEX Invoke;
	memset(&Invoke, 0, sizeof(CMINVOKECOMMANDINFOEX));
	Invoke.cbSize = sizeof(CMINVOKECOMMANDINFOEX);
	Invoke.hwnd = pHandle;
    Invoke.lpVerb = pCmdID;
    Invoke.lpDirectory = pFolderName;
	IString S(pFolderName); PWCHAR S1 = S.PWChar();
	IString S2(pCmdID); PWCHAR S3 = S2.PWChar();
    Invoke.lpVerbW = S3;
    Invoke.lpDirectoryW = S1;
	Invoke.ptInvoke = FContentMenuStartPoint;

	UINT32 M = 0;
	if (pCtrl) M |= CMIC_MASK_CONTROL_DOWN;
	if (pShift) M |= CMIC_MASK_SHIFT_DOWN;
	Invoke.fMask = CMIC_MASK_ASYNCOK | CMIC_MASK_PTINVOKE | M;// CMIC_MASK_UNICODE |
    Invoke.nShow = SW_SHOWNORMAL;
	HRESULT R = pMenu->InvokeCommand((CMINVOKECOMMANDINFO*)&Invoke); // Vykonanie prikazu

	delete S1; delete S3;
}
// ....................................................................................................................
// ....................................................................................................................
// Zobrazenie okna pre mapovanie sietoveho disku
// Vstup:
//			pParent
// Vystup:
//			Ziaden
// ....................................................................................................................
void __fastcall IShellContextMenu::ShowMapNetworkDriveWindow(HWND pParent) {
	WNetConnectionDialog(pParent, RESOURCETYPE_DISK);
}
// ....................................................................................................................
// ....................................................................................................................
// Ziskanie objektu IShellFolder pre zadanu cestu
// Vstup:
//			pPath - cesta ku priecinku
// Vystup:
//			prislusny objekt IShellFolder
// ....................................................................................................................
IShellFolder2* __fastcall IShellContextMenu::GetFolderObject(CONST_PCHAR pPath) {
		IShellFolder *DF;
		if (SHGetDesktopFolder(&DF) != S_OK) return NULL;

		IString S(pPath); PWCHAR S1 = S.PWChar();

		LPITEMIDLIST pidl;
		ULONG cbEaten;
		DWORD dwAttribs = 0;

		if (DF->ParseDisplayName(NULL, NULL, S1, &cbEaten, &pidl, &dwAttribs) != S_OK) {
			DF->Release();
			delete S1;
			return NULL;
		}
		delete S1; // Uvolnim wchar hodnotu

		LPSHELLFOLDER V;
		if (DF->BindToObject(pidl, NULL, IID_IShellFolder2, (PVOID*)&V) != S_OK) {
			CoTaskMemFree(pidl); // Uvolnim pamat
			return NULL;
		}

		CoTaskMemFree(pidl); // Uvolnim pamat
		DF->Release();
		return (IShellFolder2*)V; // Vratim objekt
}
// ....................................................................................................................
// ....................................................................................................................
// Ziskanie ITEMIDLIST z absolutnej cesty
// Vstup:
//			pPath - cesta
// Vystup:
//			struktura alebo NULL
// ....................................................................................................................
PIDLIST_ABSOLUTE __fastcall IShellContextMenu::CreateITEMIDLISTFromPath(CONST_PCHAR pPath) {
	return ILCreateFromPath(pPath); // Volam API
}
// ....................................................................................................................
// ....................................................................................................................
// Uvolnenie ITEMIDLIST struktury
// Vstup:
//			pValue - ITEMIDLIST struktura
// Vystup:
//			Ziaden
// ....................................................................................................................
void __fastcall IShellContextMenu::FreeITEMIDLIST(PIDLIST_ABSOLUTE pValue) {
	if (pValue != NULL) ::ILFree(pValue); // Uvolnim pamat
}
// ....................................................................................................................
